#include "EventClient.h"

#include "EventConfig.h"

#include <object_v2/object_v2.h>

struct _EventClient
{
        GObject parent_instance;

        /*请求类型*/
        EventRequestType request_type;

        /*班级与姓名*/
        ObjectString *user_class;
        ObjectString *user_name;

        /*明文密码*/
        ObjectString *user_password;

        /*操作条件*/
        ObjectString *item_date;
        ObjectString *item_title;
        ObjectString *item_content;

        /*配置文件*/
        EventConfig *config;
};

G_DEFINE_FINAL_TYPE(EventClient, event_client, G_TYPE_OBJECT)

static void
event_client_finalize(GObject *object)
{
        EventClient *self = EVENT_CLIENT(object);

        g_object_unref(self->config);

        object_unref(self->user_class);
        object_unref(self->user_name);
        object_unref(self->user_password);
        object_unref(self->item_date);
        object_unref(self->item_title);
        object_unref(self->item_content);

        G_OBJECT_CLASS(event_client_parent_class)->finalize(object);

        OBJECT_INFO_TOOL(EventClient, finalize, "已清理\n");
}

static void
event_client_class_init(EventClientClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS(klass);

        object_class->finalize     = event_client_finalize;
}

EventClient *
event_client_new()
{
        return g_object_new(EVENT_TYPE_CLIENT, NULL);
}

static void
event_client_append_request_with_user_info(EventClient  *self,
                                           ObjectString *request_str)
{
        object_string_append_string(request_str, self->user_class->charset);
        object_string_append_string(request_str, "&");
        object_string_append_string(request_str, self->user_name->charset);
        object_string_append_string(request_str, "&");
        object_string_append_string(request_str, self->user_password->charset);
        object_string_append_string(request_str, "&");
}

void
event_client_set_user_info(EventClient *self,
                           const char  *user_class,
                           const char  *user_name,
                           const char  *user_password)
{
        if (!user_class || !user_name || !user_password) {
                OBJECT_ERROR_TOOL(EventClient,
                                  set_user_info,
                                  "空参数！<%s>, <%s>, <%s>\n",
                                  user_class,
                                  user_name,
                                  user_password);
                return;
        }

        if (!self->user_class) {
                self->user_class    = object_string_new();
                self->user_name     = object_string_new();
                self->user_password = object_string_new();
        }

        object_string_set_string(self->user_class, user_class);
        object_string_set_string(self->user_name, user_name);
        object_string_set_string(self->user_password, user_password);

        event_config_set_user_info(self->config,
                                   user_class,
                                   user_name,
                                   user_password);
        event_config_write_config(self->config);
}

void
event_client_set_request_option(EventClient *self,
                                const char  *item_date,
                                const char  *item_title,
                                const char  *item_content)
{
        if (!self->item_date) {
                self->item_date    = object_string_new();
                self->item_title   = object_string_new();
                self->item_content = object_string_new();
        }

        if (!item_date || !item_title) {
                OBJECT_ERROR_TOOL(EventClient,
                                  set_option,
                                  "捕获到空参数！<%p>,<%p>\n",
                                  item_date,
                                  item_title);
                return;
        } else {
                object_string_set_string(self->item_date, item_date);
                object_string_set_string(self->item_title, item_title);
        }

        if (item_content)
                object_string_set_string(self->item_content, item_content);
}

ObjectString *
event_client_send_request(EventClient *self, EventRequestType request_type)
{
        GError         *error_detail = NULL;
        GSocketAddress *socket_addr;
        ObjectString   *request_str, *response_str = NULL;
        gssize          response_len;
        GSocket        *sock;
        char            buffer[10240];

        sock = g_socket_new(G_SOCKET_FAMILY_IPV4,
                            G_SOCKET_TYPE_STREAM,
                            G_SOCKET_PROTOCOL_TCP,
                            &error_detail);

        if (error_detail) {
                OBJECT_ERROR_TOOL(EventClient,
                                  send_request,
                                  "g_socket_new<%s>\n",
                                  error_detail->message);
                if (sock)
                        g_object_unref(sock);
                return NULL;
        }

        memset(buffer, 0, 10240);

        request_str = object_string_new_with("EventRequest");

        switch (request_type) {
        case EVENT_REQUEST_TYPE_INSERT:
                object_string_append_string(request_str, "insert&");
                event_client_append_request_with_user_info(self, request_str);
                object_string_append_string(request_str,
                                            self->item_date->charset);
                object_string_append_string(request_str, "&");
                object_string_append_string(request_str,
                                            self->item_title->charset);
                object_string_append_string(request_str, "&");
                object_string_append_string(request_str,
                                            self->item_content->charset);
                object_string_append_string(request_str, "&false");
                break;
        case EVENT_REQUEST_TYPE_QUERY:
                object_string_append_string(request_str, "query&");
                event_client_append_request_with_user_info(self, request_str);
                object_string_append_string(request_str, "today&21000101");
                break;
        case EVENT_REQUEST_TYPE_REMOVE:
                object_string_append_string(request_str, "remove&");
                event_client_append_request_with_user_info(self, request_str);
                object_string_append_string(request_str,
                                            self->item_date->charset);
                object_string_append_string(request_str, "&");
                object_string_append_string(request_str,
                                            self->item_title->charset);
                break;
        default:
                break;
        }

        socket_addr =
                g_inet_socket_address_new_from_string(DEFAULT_EVENT_SERVER,
                                                      DEFAULT_EVENT_PORT);
        g_socket_connect(sock, socket_addr, NULL, &error_detail);

        if (error_detail) {
                OBJECT_ERROR_TOOL(EventClient,
                                  send_request,
                                  "g_socket_connect: %s\n",
                                  error_detail->message);
                error_detail = NULL;
        }

        gssize send_size;
        send_size = g_socket_send(sock,
                                  request_str->charset,
                                  request_str->length,
                                  NULL,
                                  &error_detail);

        if (error_detail) {
                OBJECT_ERROR_TOOL(EventClient,
                                  send_request,
                                  "g_socket_send: %s\n",
                                  error_detail->message);
                error_detail = NULL;
        }

        if (send_size != request_str->length) {
                OBJECT_ERROR_TOOL(EventClient,
                                  send_request,
                                  "发送失败！(send<%d>/request<%d>)\n",
                                  (int)send_size,
                                  request_str->length);
                goto exit;
        }

        response_len =
                g_socket_receive(sock, buffer, 10240, NULL, &error_detail);

        if (!g_socket_is_closed(sock)) {
                OBJECT_DEBUG_TOOL(EventClient,
                                  send_request,
                                  "关闭活动的套接字\n");
                g_socket_close(sock, &error_detail);

                if (error_detail)
                        g_print("close_error<%s>\n", error_detail->message);

                error_detail = NULL;
        }

        if (response_len == 0) {
                OBJECT_WARNING_TOOL(EventClient,
                                    send_request,
                                    "服务器返回了空响应！\n");
                goto exit;
        }

        response_str = object_string_new_with(buffer);

exit:
        object_unref(request_str);
        g_object_unref(socket_addr);
        g_object_unref(sock);
        return response_str;
}

gboolean
event_client_read_local_user_info(EventClient *self)
{
        gboolean state   = event_config_read_config(self->config);
        self->user_class = event_config_reference_user_class(self->config);
        self->user_name  = event_config_reference_user_name(self->config);
        self->user_password =
                event_config_reference_user_password(self->config);
        return state;
}

static void
event_client_init(EventClient *self)
{
        self->user_class    = NULL;
        self->user_name     = NULL;
        self->user_password = NULL;
        self->item_date     = NULL;
        self->item_title    = NULL;
        self->item_content  = NULL;

        self->config        = event_config_new();
}
